package com.itlong.cloud.intercept;

import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.utils.network.https.HttpsPost;
import com.itlong.cloud.utils.node.JsonUtil;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 华为iot回调相关拦截器。
 *
 *@createDate 2020/01/07
 */
@Aspect
@Component
public class HuaweiIotInterceptor extends HandlerInterceptorAdapter {
    protected static final Logger LOG = LoggerFactory.getLogger(HuaweiIotInterceptor.class);
    @Value("${" + PlatformConstants.HUAWEI_IOT_APPID + "}")
    private String appid;
    @Value("${" + PlatformConstants.HUAWEI_IOT_SECRET + "}")
    private String secret;
    @Value("${" + PlatformConstants.HUAWEI_PROJECT_ID + "}")
    private String projectId;
    // 定义一个切入点
    @Pointcut("execution(* com.itlong.cloud.controller.huawei.*.*(..)) && !@annotation(com.itlong.cloud.annotation.UnAuthAccessRequired)")
    public void excudeService(){}

    @Autowired
    RedisService redisService;


    /**
     * check入参并处理相关信息
     */
    @Before("excudeService()")
    public Object twiceAsOld() throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        try {
            String jsonStr = getRequestPostStr(request);
            if (StringUtils.isBlank(jsonStr)) {
                return null;
            }
            LOG.info("【华为云推送url】："+request.getRequestURI()+";华为推送信息:"+jsonStr);
            Map<String,Object> data = JsonUtil.toObject(jsonStr, HashMap.class);
            if(data.get("resource") !=null && data.get("resource").toString().equals("device.data")) {
                Map<String, Object> notifyData = (HashMap) data.get("notify_data");
                String deviceUnique = notifyData.get("device_id").toString();
                String result = this.getDeviceRedis(deviceUnique);
                Map<String, Object> resultMap = JsonUtil.toObject(result, HashMap.class);
                List<Map<String, Object>> services = (ArrayList) notifyData.get("services");
                request.setAttribute("jsonStr", JsonUtil.toJSON(services));
                request.setAttribute("deviceUnique", resultMap.get("device_name").toString());
            }else if (data.get("resource") !=null && data.get("resource").toString().equals("device.status")) {
                Map<String, Object> notifyData = (HashMap) data.get("notify_data");
                //做兼容处理
                if(notifyData != null){
                    String deviceUnique = notifyData.get("device_id").toString();
                    String result = this.getDeviceRedis(deviceUnique);
                    Map<String, Object> resultMap = JsonUtil.toObject(result, HashMap.class);
                    request.setAttribute("jsonStr", jsonStr);
                    request.setAttribute("deviceUnique", resultMap.get("device_name").toString());
                }else {
                    String deviceUnique = data.get("deviceId").toString();
                    String result =this.getDeviceRedis(deviceUnique);
                    Map<String, Object> resultMap = JsonUtil.toObject(result, HashMap.class);
                    request.setAttribute("jsonStr", jsonStr);
                    request.setAttribute("deviceUnique", resultMap.get("device_name").toString());
                }

            }else{
                String deviceUnique = data.get("deviceId").toString();
                String result =this.getDeviceRedis(deviceUnique);
                Map<String, Object> resultMap = JsonUtil.toObject(result, HashMap.class);
                request.setAttribute("jsonStr", jsonStr);
                request.setAttribute("deviceUnique", resultMap.get("device_name").toString());
            }
        } catch (Exception e) {
            LOG.error("【华为调用数据上报失败】",e);
        }
        return true;
    }

    /**
     * <desc>
     *      查询设备数据
     * </desc>
     *
     * @param deviceUnique
     * @return
     * @throws IOException
     * @author Jiaqi.X
     * @createDate 2020/04/13
     */
    private String getDeviceRedis(String deviceUnique) throws IOException {
        //华为配置信息start
        LOG.info("【华为配置的信息为 appId projectId】{} {}", appid, projectId);
        //华为配置信息end
        String deviceStr = redisService.get(RedisConstant.HUAWEI_IOT_DEVICE_ID_KEY+deviceUnique);
        if(StringUtils.isBlank(deviceStr)){
            String result = HttpsPost.doGet(this.getAccessToken(), "https://iotdm.cn-north-4.myhuaweicloud.com/v5/iot/" + projectId + "/devices/" + deviceUnique, null);
            Map<String, Object> resultMap = JsonUtil.toObject(result, HashMap.class);
            if(resultMap.get("error_code") != null){
                redisService.del(RedisConstant.HUAWEI_ACCESS_TOKEN_REDIS_KEY);
                result = HttpsPost.doGet(this.getAccessToken(), "https://iotdm.cn-north-4.myhuaweicloud.com/v5/iot/" + projectId + "/devices/" + deviceUnique, null);
                LOG.info("【查询华为云iot设备信息返回结果】" + result);
            }
            redisService.set(RedisConstant.HUAWEI_IOT_DEVICE_ID_KEY+deviceUnique,RedisConstant.HUAWEI_IOT_DEVICE_ID_CACHE_TIME,result);
            deviceStr = result;
        }
        return deviceStr;
    }

    /**
     * 描述:获取 post 请求的 byte[] 数组
     * <pre>
     * 举例：
     * </pre>
     * @param request
     * @return
     * @throws IOException
     */
    public static byte[] getRequestPostBytes(HttpServletRequest request)
            throws IOException {
        int contentLength = request.getContentLength();
        if(contentLength<0){
            return null;
        }
        byte buffer[] = new byte[contentLength];
        for (int i = 0; i < contentLength;) {

            int readlen = request.getInputStream().read(buffer, i,
                    contentLength - i);
            if (readlen == -1) {
                break;
            }
            i += readlen;
        }
        return buffer;
    }

    /**
     * 描述:获取 post 请求内容
     * <pre>
     * 举例：
     * </pre>
     * @param request
     * @return
     * @throws IOException
     */
    public static String getRequestPostStr(HttpServletRequest request)
            throws IOException {
        byte buffer[] = getRequestPostBytes(request);
        String charEncoding = request.getCharacterEncoding();
        if (charEncoding == null) {
            charEncoding = "UTF-8";
        }
        return new String(buffer, charEncoding);
    }

    private String getAccessToken(){
        try {
            if(redisService.get(RedisConstant.HUAWEI_ACCESS_TOKEN_REDIS_KEY) == null){
                //获取accesstoken
                String token = this.getToken();
                redisService.set(RedisConstant.HUAWEI_ACCESS_TOKEN_REDIS_KEY, RedisConstant.HUAWEI_ACCESS_TOKEN_REDIS_CACHE_TIME, token);
                return token;
            }else{
                return redisService.get(RedisConstant.HUAWEI_ACCESS_TOKEN_REDIS_KEY);
            }
        }catch (Exception e){
            return null;
        }
    }

    /**
     * <desc>
     *      获取华为云api调用token
     * </desc>
     *
     * @return
     * @throws Exception
     * @author Jiaqi.X
     * @createDate 2020/02/13
     */
    private String getToken() throws Exception {
        Map<String,Object> params = new HashMap<>();
        Map<String,Object> auth = new HashMap<>();
        Map<String,Object> identity = new HashMap<>();
        Map<String,Object> password = new HashMap<>();
        Map<String,Object> user = new HashMap<>();
        Map<String,Object> domain = new HashMap<>();
        Map<String,Object> scope = new HashMap<>();
        Map<String,Object> project = new HashMap<>();
        String[] method = new String[]{"password"};
        user.put("name",appid);
        user.put("password",secret);
        user.put("domain",domain);
        domain.put("name",appid);
        project.put("name","cn-north-4");
        scope.put("project",project);
        password.put("user",user);
        identity.put("methods",method);
        identity.put("password",password);
        auth.put("identity",identity);
        auth.put("scope",scope);
        params.put("auth",auth);
        String token = HttpsPost.doPostToken(PlatformConstants.HUAWEI_TOKEN_URL, params);
        return token;
    }
}
